package ecs.core;

import ecs.net.EventType;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public abstract class BaseSystem implements ISystem {

    private IScene _parent;
    private Class<?>[] _interestingComponentTypes;
    private final List<List<IComponent>> _entityComponents;

    public BaseSystem() {
        _entityComponents = new ArrayList<>();
    }

    public Class<?>[] interestingComponentTypes() {
        return _interestingComponentTypes;
    }

    public void interestingComponentTypes(Class<?>[] types) {
        _interestingComponentTypes = types;
    }

    private volatile boolean _enable;

    public boolean enable() {
        return _enable;
    }

    public void enable(boolean enable) {
        _enable = enable;
    }

    protected List<List<IComponent>> entityComponents() {
        return _entityComponents;
    }

    @Override
    public <T extends IScene> void parent(T scene) {
        _parent = scene;
    }

    @SuppressWarnings("unchecked")
    @Override
    public <T extends IScene> T parent() {
        return (T) _parent;
    }

    @Override
    public <T extends IEntity> void entry(T entity) {
        List<IComponent> components = entity.components(interestingComponentTypes());
        if (!components.isEmpty()) {
            entityComponents().add(components);
        }
    }

    @Override
    public <T extends IEntity> void quit(T entity) {
        for (Class<?> type : interestingComponentTypes()) {
            entity.remove(type);
        }
    }

    @Override
    public void broadcast(EventType type, Object param) {
        parent().broadcast(type, param);
    }

    public void broadcast(EventType type) {
        parent().broadcast(type, null);
    }

    @Override
    public void handle(EventType event, Object param) {
        switch (event) {
            case EntityIn -> {
                IEntity entity = (IEntity) param;
                entityComponents().add(new ArrayList<>(entity.components(interestingComponentTypes())));
            }
            default -> {
            }
        }
    }

    @Override
    public void start() {
        enable(true);
    }

    @Override
    public void stop() {
        enable(false);
    }
}
